"use strict";
var SceneManager = function(camprop,container,canvas) {
    this.prop = camprop;
    this.container = container;
    this.canvas = canvas;
    this.rendererExtension = null;

    this.init();
};

SceneManager.prototype = {

    init: function() {
        
        this.createScene();
        this.createRenderer();
        this.configCamera();
        
        this.initLight();
        this.createClock();

        
        this.createRendererExtension();

        // this.configState();

        this.animate();
    },

    createScene: function() {
        if (!this.prop.scene) {
         this.prop.scene = new THREE.Scene();
         this.prop.scene.add( this.createSphereGeometry() );
        }
    },
    configCamera: function() {  //透视相机
        if(!this.prop.camera) {
          this.prop.camera = new THREE.PerspectiveCamera(this.prop.fov, window.innerWidth / window.innerHeight, this.prop.near, this.prop.far);//透视投影,即远景相机,模仿人眼
        }
        
        this.prop.camera.target = new THREE.Vector3( 0, 0, 0 );//初始化相机观察点//(小行星视觉)this.camera.position.set(0, 450, 0);//150
        this.prop.camera.lookAt( this.prop.camera.target );
        this.prop.camera.position.set(0, 150, 168);
        this.prop.camera.up.set(0,1,0);//相机朝向--相机上方为y轴

        this.prop.scene.add(this.prop.camera);
     },
    initLight: function() { 
        var hemiLight = new THREE.HemisphereLight(0x0000ff, 0x00ff00, 0.6);
        hemiLight.position.set(0, 500, 0);
        this.prop.scene.add(hemiLight);
    },

    createRendererExtension:function() {
        this.rendererExtension = new RendererExtension(this.prop);
        this.rendererExtension.configStereoEffect(true);
        // Our initial control fallback with mouse/touch events in case DeviceOrientation is not enabled
        this.rendererExtension.configOrbitControls();
    },

    createTexture: function(_canvas) {
        if(!this.prop.texture) {
          this.prop.texture = new THREE.Texture(_canvas);
          // this.prop.texture = textureLoader.load("./image/" + "city2_bg" + ".jpg");
        }
        this.prop.texture.minFilter = THREE.LinearFilter;//纹理在缩小时的过滤方式,默认THREE.LinearMipMapNearestFilter选择最临近的mip层，并执行线性过滤
        this.prop.texture.magFilter = THREE.LinearFilter;
        this.prop.texture.format = THREE.RGBFormat;//像素数据的颜色格式, 默认为THREE.RGBAFormat,还有以下可选参数
    },
    createSphereGeometry: function() {

        if(!this.prop.texture) {
          this.createTexture(this.canvas);
        }
        
        var material = new THREE.MeshBasicMaterial( { map: this.prop.texture } );
        var geometry = new THREE.SphereGeometry(500, 60, 40 );// 500, 60, 40、3,20,8建立半径为500,水平垂直分割面分别为60,40的缓冲球面
        geometry.scale(  -1, 1, 1 );//进行缩放，进行矩阵变换,将视频贴在球内表面
        geometry.rotateY(Math.PI / 2)
        return new THREE.Mesh(geometry, material);

    },

    createRenderer: function() {
        if (!this.prop.renderer) {
            if ( this.webglAvailable() ) {
                this.prop.renderer = new THREE.WebGLRenderer();
            } else {
                this.prop.renderer = new THREE.CanvasRenderer();
            }
        }
        this.prop.renderer.setPixelRatio(window.devicePixelRatio);//返回当前设备的像素比
		this.prop.renderer.setSize( window.innerWidth, window.innerHeight );
        this.prop.renderElement = this.prop.renderer.domElement;

        this.container.appendChild(this.prop.renderElement);
    },

    webglAvailable: function() {
        try {
          return !!( window.WebGLRenderingContext && (this.canvas.getContext( 'webgl' ) || this.canvas.getContext( 'experimental-webgl' ) ));
        } catch ( e ) {
          return false;
        }
    },

    // configState: function() {
    //     this.prop.debugStats = new Stats();  
    //     this.prop.debugStats.setMode(0); // 0: fps, 1: ms

    //     this.prop.debugStats.domElement.style.position = 'absolute'; //绝对坐标  
    //     this.prop.debugStats.domElement.style.left = '0px';// (0,0)px,左上角  
    //     this.prop.debugStats.domElement.style.top = '0px';  
    //     this.container.appendChild(this.prop.debugStats.domElement);  
    // },


    createClock: function() {
        if (!this.prop.clock) {
         this.prop.clock = new THREE.Clock();
        }
    },

    animate: function() {
        requestAnimationFrame(this.animate.bind(this));

        var dt = this.prop.clock.getDelta()
        this.update(dt);
    },

    resizeGL: function() {
        var width = this.container.offsetWidth;
        var height = this.container.offsetHeight;

        this.prop.camera.aspect = width / height;
        this.prop.camera.updateProjectionMatrix();

        this.prop.renderer.setSize(width, height);
        this.prop.stereoEffect.setSize(width, height);
    },

    update: function(dt) {
        this.render(dt);
    },

    render: function(dt) {
        this.resizeGL();
        TWEEN.update();
        this.prop.texture.needsUpdate = true;

        if (this.prop.orbitControls) {
          this.prop.orbitControls.update(dt);
        }
        if (this.prop.orientationControls ) {
          this.prop.orientationControls.update(dt);
        }
        
        // this.prop.debugStats.update(dt);
        if(this.prop.reticle) this.prop.reticle.gazer.update(this.prop.camera, dt);
        
        if(this.prop.isStereoEnable){
            this.prop.stereoEffect.render(this.prop.scene, this.prop.camera);
        }else{
            this.prop.renderer.render(this.prop.scene, this.prop.camera);
        }
        
        // this.renderMarkers();
    },

    toggleDeviceOrientation: function() {
        this.rendererExtension.configDeviceOrientation();
    },

      // const settings = {
  //   minArea: 20,
  //   maxVisibleDot: -0.2,
  // };
  // const gui = new GUI({width: 300});
  // gui.add(settings, 'minArea', 0, 50).onChange(requestRenderIfNotRequested);
  // gui.add(settings, 'maxVisibleDot', -1, 1, 0.01).onChange(requestRenderIfNotRequested);

    renderMarkers: function() {

        const tempV = new THREE.Vector3();
        const cameraToPoint = new THREE.Vector3();
        const cameraPosition = new THREE.Vector3();
        const normalMatrix = new THREE.Matrix3();
        // const large = settings.minArea * settings.minArea;
        // get a matrix that represents a relative orientation of the camera
        normalMatrix.getNormalMatrix(this.prop.camera.matrixWorldInverse);
        // get the camera's position
        this.prop.camera.getWorldPosition(cameraPosition);


        var position = transform.sphericalCoordsToVector3(-77.02182,38.53707,earthBallSize);


        // Orient the position based on the camera's orientation.
        // Since the sphere is at the origin and the sphere is a unit sphere
        // this gives us a camera relative direction vector for the position.
        tempV.copy(position);
        tempV.applyMatrix3(normalMatrix);

        // compute the direction to this position from the camera
        cameraToPoint.copy(position);
        cameraToPoint.applyMatrix4(this.prop.camera.matrixWorldInverse).normalize();

        // get the dot product of camera relative direction to this position
        // on the globe with the direction from the camera to that point.
        // -1 = facing directly towards the camera
        // 0 = exactly on tangent of the sphere from the camera
        // > 0 = facing away
        const dot = tempV.dot(cameraToPoint);

        // if the orientation is not facing us hide it.
        // if (dot > -0.2) {
        //   elem.style.display = 'none';
        //   return;
        // }
        

        // restore the element to its default display style
        elem.style.display = '';

        // get the normalized screen coordinate of that position
        // x and y will be in the -1 to +1 range with x = -1 being
        // on the left and y = -1 being on the bottom
        tempV.copy(position);
        tempV.project(this.prop.camera);

        // var tempV = this.vector3ToViewerCoords(position);

        // convert the normalized position to CSS coordinates
        const x = (tempV.x *  .5 + .5) * this.prop.renderElement.clientWidth;
        const y = (tempV.y * -.5 + .5) * this.prop.renderElement.clientHeight;

        // move the elem to that position
        elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;

        // set the zIndex for sorting
        elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
    }
};